import { reactive } from "vue";
import Nifi from "../nifi";
import { FlowKeys } from "../util";

interface Group extends Record<string, any> {
    id: string;
    flow: any;
    breadcrumb: Record<string, {
        id: string;
        name: string;
        next?: string;
        prev?: string;
    }>;
    breadcrumbIds: string[];
    refresh: (id?: string) => Promise<void>
    add: (flow: any) => void
    diff: (flow: any) => void
    update: (data: any) => void
    refreshFlowGroup: (id?: string) => Promise<void>
    refreshGroupData: (id?: string) => Promise<any>
    refreshGroupStatus: (id?: string) => Promise<any>
    goToCell: (groupId: string, id: string) => Promise<void>
}

const initBreadcrumb = (data: any, cid?: string) => {
    const { breadcrumb, parentBreadcrumb } = data
    const { id, name } = breadcrumb;
    const res: any = {};
    const ids = [id]
    res[id] = cid ? { name, id, next: cid } : { name, id }
    if (parentBreadcrumb) {
        res[id].prev = parentBreadcrumb.id
        const [t, ts] = initBreadcrumb(parentBreadcrumb, breadcrumb.id)
        Object.assign(res, t);
        ids.push(...ts)
    }
    return [res, ids];
}

export default (nifi: Nifi) => {
    const getFlowGroup = async (id: string) => await nifi.api.get(`/nifi-api/flow/process-groups/${id}?uiOnly=true`)
    const getGroupData = async (id: string) => await nifi.api.get(`/nifi-api/process-groups/${id}?uiOnly=true`)
    const getGroupStatus = async (id: string) => await nifi.api.get(`/nifi-api/flow/process-groups/${id}/status`)
    //
    const refreshFlowGroup = async (id = group.id || nifi.rootId) => {
        try {
            const { processGroupFlow } = await getFlowGroup(id);
            group.flow = processGroupFlow.flow;
            const [d, ids] = initBreadcrumb(processGroupFlow.breadcrumb)
            Object.assign(group.breadcrumb, d)
            group.breadcrumbIds.length = 0;
            group.breadcrumbIds.push(...ids)
        } catch (error) {
            console.error('refreshFlowGroup :: ',error)
        }

        console.log('refreshFlowGroup--------------')
    }
    const refreshGroupData = async (id = group.id || nifi.rootId) => {
        const data = await getGroupData(id)
        Object.assign(group, data)
        return data;
    }
    const refreshGroupStatus = async (id = group.id || nifi.rootId) => {
        const res = await getGroupStatus(id)
        const status = res?.processGroupStatus;
        if (status && group.status) {
            Object.assign(group.status, status)
        }
        return status;
    }
    const refresh = async (id = group.id || nifi.rootId) => {
        console.log('refresh--------------')
        nifi.currentId.value = id;
        nifi.key = id;
        nifi.drawer.close();
        nifi.graph.loading.value = true;
        await refreshGroupData(id);
        await refreshFlowGroup(id);
        //
        nifi.layout.clearExcludeIds();
        render();
        nifi.graph.loading.value = false;
    }
    //
    const update = (data: any) => {
        if (data) {
            Object.assign(group, data)
        }
    }
    //
    //
    const getCells = (flow = group.flow) => {
        const cells = []
        for (const k of FlowKeys) {
            // @ts-ignore
            const cs: any[] = nifi.cells[k as IPackNifi.NIFI_CAMEL_NAME]?.init(flow[k], cells) || [];
            cells.push(...cs);
        }
        // 将 labels 排除在布局之外
        const lids = flow.labels.map((d: any) => d.id)
        nifi.layout.addExcludeIds(lids)
        //
        return cells;
    }
    const render = () => {
        if (group.flow == undefined) return;
        nifi.graph.recoverConfig();
        if (nifi.graph.isInit) {
            nifi.graph.refresh(getCells())
        }
        else {
            nifi.graph.onMounted(() => {
                nifi.graph.refresh(getCells())
            })
        }
    }
    // 增量渲染
    const add = (flow: any) => {
        if (!nifi.graph.isInit) return;
        const cells = getCells(flow)
        nifi.graph.addCell(cells)
    }
    // diff 渲染 依据新给的数据，找出需要移除和新增的节点，调用相关的方法移除多余的元素，增加新的元素
    const diff = (flow: any) => {
        if (!nifi.graph.isInit) return;
        const cells = getCells(flow)
        nifi.graph.change({ cells })
    }

    const goToCell = async (groupId: string, id: string) => {
        if (groupId != nifi.group.id) {
            await refresh(groupId);
        }
        nifi.graph.centerCell(nifi.graph.getCellById(id));
        nifi.graph?.resetSelection(id)
    }
    //
    const group: Group = { id: "", flow: undefined, breadcrumb: {}, breadcrumbIds: reactive([]), refresh, add, diff, refreshFlowGroup, refreshGroupData, update, goToCell, refreshGroupStatus }
    //
    return group;
}